package org.sean.framework.context;

import org.sean.framework.util.ObjectUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * 获取 Spring ApplicationContext
 */
@Configuration
@SuppressWarnings("unchecked")
public class SpringApplicationContext implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    /**
     * 获取Bean 实例
     *
     * @param <T>  T
     * @param name 实例名
     * @return 实例
     */
    public static <T> T getBean(String name) {
        try {
            return (T) ObjectUtil.getTarget(applicationContext.getBean(name));
        } catch (Exception e) {
            // do nothing
        }
        return null;
    }

    /**
     * 获取Bean 实例
     *
     * @param <T>   T
     * @param clazz 类型
     * @return 实例
     */
    public static <T> T getBean(Class<T> clazz) {
        try {
            return ObjectUtil.getTarget(applicationContext.getBean(clazz));
        } catch (Exception e) {
            // do nothing
        }
        return null;
    }

    /**
     * 获取Bean 实例
     *
     * @param <T>  T
     * @param type 类型
     * @return 实例
     */
    public static <T> Map<String, T> getBeansOfType(Class<T> type) {
        try {
            return applicationContext.getBeansOfType(type);
        } catch (Exception e) {
            // do nothing
        }
        return null;
    }

    /**
     * 获取Bean 实例
     *
     * @param <T>                  T
     * @param type                 类型
     * @param includeNonSingletons 包含多实例
     * @param allowEagerInit       懒加载实例
     * @return 实例
     */
    public static <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) {
        try {
            return applicationContext.getBeansOfType(type, includeNonSingletons, allowEagerInit);
        } catch (Exception e) {
            // do nothing
        }
        return null;
    }

    /**
     * 事件发布
     *
     * @param event 事件
     */
    public static void publishEvent(ApplicationEvent event) {
        applicationContext.publishEvent(event);
    }

    @Override
    public void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }
}
